package engine;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Scanner;
import java.util.TreeMap;
import java.util.logging.Level;
import java.util.logging.Logger;

public class IndexReader {

    private String indexPath;
    private String docPathMapping;
    private String tfIdfPath;
    private ArrayList<String> vocabulary;

    public IndexReader(String indexPath, String tfIdfPath, String docPathMapping) {
        this.indexPath = indexPath;
        this.docPathMapping = docPathMapping;
        this.tfIdfPath = tfIdfPath;

        this.vocabulary = null;
    }

    public String getIndexPath() {
        return indexPath;
    }

    public String getTfIdfPath() {
        return tfIdfPath;
    }

    public String getDocPathMapping() {
        return docPathMapping;
    }

    public ArrayList<String> getVocabulary() throws IOException {
        if (this.vocabulary != null) {
            return this.vocabulary;
        }

        this.vocabulary = new ArrayList<String>();
        String curLine;
        int lineNumber = 0;
        try (Scanner scanner = new Scanner(Paths.get(indexPath))) {
            while (scanner.hasNextLine()) {
                curLine = scanner.nextLine();

                if (lineNumber <= 27) {
                } else {
                    this.vocabulary.add(curLine.substring(0, curLine.indexOf(":")));
                }
                lineNumber++;
            }
        }

        return this.vocabulary;
    }

    public String getDocPath(String docID) throws IOException {
        String[] line;
        try (Scanner scanner = new Scanner(Paths.get(this.docPathMapping))) {
            while (scanner.hasNextLine()) {
                line = scanner.nextLine().split(";");
                if ((line[0]).equals(docID)) {
                    return line[1];
                }
            }
        }

        return null;
    }
    
    public String getDocPath(Integer docID) throws IOException {
        String[] line;
        try (Scanner scanner = new Scanner(Paths.get(this.docPathMapping))) {
            while (scanner.hasNextLine()) {
                line = scanner.nextLine().split(";");
                if ((line[0]).equals("D" + docID)) {
                    return line[1];
                }
            }
        }

        return null;
    }

    public String getDocId(String docPath) throws IOException {
        String[] line;
        try (Scanner scanner = new Scanner(Paths.get(this.docPathMapping))) {
            while (scanner.hasNextLine()) {
                line = scanner.nextLine().split(";");
                if ((line[1]).equals(docPath)) {
                    return line[0];
                }
            }
        }

        return null;
    }
    

    public TreeMap<String, ArrayList<Double>> getAllDocWeigths() throws IOException {
        TreeMap<String, ArrayList<Double>> weights = new TreeMap<String, ArrayList<Double>>();
        String[] line;
        String[] values;
        ArrayList<Double> dValues;

        //lire l'index tfIdf
        try (Scanner scanner = new Scanner(Paths.get(this.tfIdfPath))) {
            while (scanner.hasNextLine()) {
                line = scanner.nextLine().split(":");
                values = line[1].split(";");
                dValues = new ArrayList<Double>();
                for (String v : values) {
                    dValues.add(Double.parseDouble(v));
                }

                weights.put(getDocPath(line[0]), dValues);
            }
        }

        return weights;
    }

    public double idfWordFromIndex(String word) {
        int nbDoc = 0;
        double result = -1.00;
        InputStream ips;

        try {
            ips = new FileInputStream(this.indexPath);
            InputStreamReader ipsr = new InputStreamReader(ips);
            BufferedReader br = new BufferedReader(ipsr);
            String line;

            try {
                int count = 0;
                //Lecture des lignes
                boolean charFound = false;
                int start = 0;
                int end = 0;
                boolean wordFound = false;
                boolean finish = false;

                while (finish == false && (line = br.readLine()) != null) {
                    if (count == 0) {
                        String[] elt = new String[2];
                        elt = line.split(":");
                        nbDoc = Integer.parseInt(elt[1]);
                    }
                    if (charFound == false) {
                        if (line.charAt(0) == word.charAt(0)) {
                            String[] elt = new String[3];
                            elt = line.split(":");
                            start = Integer.parseInt(elt[1]);
                            end = Integer.parseInt(elt[2]);
                            charFound = true;
                        }
                    } else {
                        if (count >= start && count < end + 1) {
                            String[] elt = new String[2];
                            elt = line.split(":");
                            if (elt[0].compareTo(word) == 0) {
                                wordFound = true;
                                finish = true;
                                String[] array = elt[1].split(",");
                                result = Math.log10((double) (nbDoc) / (double) (array.length));
//                                System.out.println("NbDoc" + nbDoc);
//                                System.out.println("DF" + array.length);
//                                System.out.println("Fuck" + Math.log10(119.00 / 4.00));
                                return result;
                            } else if (elt[0].compareTo(word) > 0) {
                                finish = true;
                            }
                        }
                        if (count > end + 1) {
                            finish = true;
                        }
                    }
                    count++;
                }
            } catch (IOException ex) {
            }
        } catch (FileNotFoundException ex) {
        }
        return result;
    }

    public ArrayList<String> getWordBeginsWith(String prefix) {
        ArrayList<String> result = new ArrayList<String>();
        InputStream ips;

        try {
            ips = new FileInputStream(this.indexPath);
            InputStreamReader ipsr = new InputStreamReader(ips);
            BufferedReader br = new BufferedReader(ipsr);
            String line;

            try {
                int count = 0;
                //Lecture des lignes
                boolean charFound = false;
                int start = 0;
                int end = 0;
                boolean finish = false;
                while (finish == false && (line = br.readLine()) != null) {
                    if (charFound == false) {
                        if (line.charAt(0) == prefix.charAt(0)) {
                            String[] elt = new String[3];
                            elt = line.split(":");
                            start = Integer.parseInt(elt[1]);
                            end = Integer.parseInt(elt[2]);
                            charFound = true;
                        }
                    } else {
                        if (count >= start && count < end + 1) {
                            String[] elt = new String[2];
                            elt = line.split(":");
                            if (elt[0].indexOf(prefix) == 0) {
                                result.add(elt[0]);
                            }
                        }
                        if (count > end + 1) {
                            finish = true;
                        }
                    }
                    count++;
                }
            } catch (IOException ex) {
            }
        } catch (FileNotFoundException ex) {
        }
        return result;
    }

    public HashMap<String, Double> makeVectorFromRequest(String request) {
        ArrayList<String> voc = null;
        try {
            voc = getVocabulary();
        } catch (IOException ex) {}
        
        //Calcul du vecteur tfIdf de la requete
        HashMap<String, Double> requestWeights = new HashMap<String, Double>();

        //System.out.println("voc size=" + voc.size());
        for (int i = 0; i < voc.size(); i++) {
            requestWeights.put(voc.get(i), 0.);
        }

        for (String word : request.split("\\s+")) {
            //System.out.println("indexReader.idfWordFromIndex(word)=" + indexReader.idfWordFromIndex(word));
            requestWeights.put(word, idfWordFromIndex(word));
        }
        
        return requestWeights;
    }
}
